package com.itrident.store;

import com.intellij.lang.jvm.JvmParameter;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.PsiEnumConstantImpl;
import com.intellij.psi.impl.source.PsiJavaFileImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.itrident.handler.RecodeEnumsHandler;
import com.itrident.util.IdeaUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author cxx
 * @create 2021-04-12 17:29
 **/
@State(name = "EnumsManagerPersistentState",storages = @Storage("rxenmus.xml"))
public class EnumsManagerPersistentState implements PersistentStateComponent<EnumsManager> {

    private EnumsManager enumsManager = new EnumsManager ();

    public static EnumsManagerPersistentState getInstance(Project project){
        return ServiceManager.getService (project, EnumsManagerPersistentState.class);
    }

    @Nullable
    @Override
    public EnumsManager getState() {
        return enumsManager;
    }

    @Override
    public void loadState(@NotNull EnumsManager state) {
        this.enumsManager = state;
    }

    public List<EnumsWrapper> getEnumsWrapper(){
        return this.enumsManager.getList ();
    }

    public void addEnumsWrapper(PsiFile psiFile,String className) {
        delEnumsWrapper (className);
        Project project = psiFile.getProject ();
        PsiClassImpl psiClass = ((PsiJavaFileImpl) psiFile).findChildByClass (PsiClassImpl.class);
        PsiField[] fields = psiClass.getFields ();
        EnumsWrapper enumsWrapper = new EnumsWrapper ();
        enumsWrapper.setClassName (className);
        List<EnumsInfo> enumsInfos = enumsWrapper.getEnumsInfos ();
        PsiMethod[] constructors = psiClass.getConstructors ();
        JvmParameter[] parameters = null;
        if(constructors.length != 0){
            parameters = constructors[0].getParameters ();
        }
        if(parameters == null || parameters.length == 0){
            EnumsInfo enumsInfo = null;
            for (PsiField field : fields) {
                if (field instanceof PsiEnumConstantImpl) {
                    String variableName = field.getName ();
                    enumsInfo =new EnumsInfo (variableName,"");
                    enumsInfos.add (enumsInfo);
                }
            }
        }else{
            int codeIndex = getCodeIndex (project,psiClass, parameters);
            int descIndex = getDescIndex(project,psiClass, parameters);
            EnumsInfo enumsInfo = null;
            String pattern = "^.+\\((\".+\")+\\)";
            Pattern compile = Pattern.compile (pattern);
            for (PsiField field : fields) {
                if (field instanceof PsiEnumConstantImpl) {
                    String text = field.getText ();
                    Matcher matcher = compile.matcher (text);
                    if (matcher.find ()) {
                        String[] params = matcher.group (1).replaceAll ("\"", "").split (",");
                        String code = params[codeIndex].trim ();
                        String desc = descIndex != -1 ? params[descIndex].trim () : "";
                        enumsInfo =new EnumsInfo (code,desc);
                        enumsInfos.add (enumsInfo);
                    }
                }
            }
        }
        if(enumsWrapper.getEnumsInfos ().size () > 0){
            this.addEnumsWrapper (enumsWrapper);
        }
    }


    public void addEnumsWrapper(EnumsWrapper enumsWrapper){
        this.enumsManager.getList ().add (enumsWrapper);
    }

    public void delEnumsWrapper(String className){
        this.enumsManager.getList ().remove (new EnumsWrapper (className));
    }

    public boolean isExist(String className) {
        return this.enumsManager.getList ().contains (new EnumsWrapper (className));
    }

    private int getDescIndex(Project project, PsiClassImpl psiClass, JvmParameter[] parameters) {
        String fieldName = RecodeEnumsHandler.getDesc (project);
        if(parameters.length == 1){
            return -1;
        }
        if(fieldName == null){
            return 1;
        }
        PsiField psiFieldCode = null;
        int i = 0;
        for (JvmParameter parameter : parameters) {
            if (parameter.getName ().equals (fieldName)) {
                psiFieldCode = psiClass.findFieldByName (fieldName, false);
                if(psiFieldCode != null){
                    return i;
                }
            }
            i++;
        }
        return 1;
    }

    private int getCodeIndex(Project project, PsiClassImpl psiClass, JvmParameter[] parameters) {
        String fieldName = RecodeEnumsHandler.getCode (project);
        if(fieldName == null){
            return 0;
        }
        PsiField psiFieldCode = null;
        int i = 0;
        for (JvmParameter parameter : parameters) {
            if (parameter.getName ().equals (fieldName)) {
                psiFieldCode = psiClass.findFieldByName (fieldName, false);
                if(psiFieldCode != null){
                    return i;
                }
            }
            i++;
        }
        return 0;
    }


    public void delAll() {
        this.enumsManager.getList ().clear ();
    }

    public void reload(Project project) {
        List<EnumsWrapper> list = this.getEnumsWrapper ();
        if (list != null && list.size () > 0) {
            GlobalSearchScope allScope = GlobalSearchScope.allScope (project);
            EnumsManagerPersistentState enumsManagerPersistentState = EnumsManagerPersistentState.getInstance (project);
            for (EnumsWrapper enumsWrapper : list) {
                PsiClass psiClass = JavaPsiFacade.getInstance (project).findClass (enumsWrapper.getClassName (), allScope);
                if (psiClass != null) {
                    enumsManagerPersistentState.addEnumsWrapper (psiClass.getContainingFile (), enumsWrapper.getClassName ());
                }
            }
        }
    }
}
